package sunyu.quartz.common;

import com.jfinal.kit.PropKit;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class CommonSchedulerFactoryBean implements ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(CommonSchedulerFactoryBean.class);

    private ApplicationContext applicationContext;
    private String applicationContextSchedulerContextKey = PropKit.use("config-quartz.properties").get("quartz.applicationContextSchedulerContextKey");
    private String waitForJobsToCompleteOnShutdown = PropKit.use("config-quartz.properties").get("quartz.waitForJobsToCompleteOnShutdown");
    private String schedulerName = PropKit.use("config-quartz.properties").get("quartz.schedulerName");
    private String dataSource = PropKit.use("config-quartz.properties").get("quartz.dataSource");
    private String startupDelay = PropKit.use("config-quartz.properties").get("quartz.startupDelay");
    private String overwriteExistingJobs = PropKit.use("config-quartz.properties").get("quartz.overwriteExistingJobs");
    private String autoStartup = PropKit.use("config-quartz.properties").get("quartz.autoStartup");
    private String instanceName = PropKit.use("config-quartz.properties").get("quartz.scheduler.instanceName");
    private String instanceId = PropKit.use("config-quartz.properties").get("quartz.scheduler.instanceId");
    private String jobStoreClass = PropKit.use("config-quartz.properties").get("quartz.jobStore.class");
    private String tablePrefix = PropKit.use("config-quartz.properties").get("quartz.jobStore.tablePrefix");
    private String isClustered = PropKit.use("config-quartz.properties").get("quartz.jobStore.isClustered");
    private String clusterCheckinInterval = PropKit.use("config-quartz.properties").get("quartz.jobStore.clusterCheckinInterval");

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void init() {
        logger.info("动态注册SchedulerFactoryBean，自动扫描Applicationcontext中，所有类型为CronTriggerFactoryBean的类，注入到SchedulerFactoryBean中");

        Map<String, CronTriggerFactoryBean> beans = applicationContext.getBeansOfType(CronTriggerFactoryBean.class);
        List<Trigger> triggers = new ArrayList<>();//所有需要动态注入的触发任务
        for (Map.Entry<String, CronTriggerFactoryBean> entry : beans.entrySet()) {
            triggers.add(entry.getValue().getObject());
        }

        Properties properties = new Properties();
        properties.put("org.quartz.scheduler.instanceName", instanceName);
        properties.put("org.quartz.scheduler.instanceId", instanceId);
        properties.put("org.quartz.jobStore.class", jobStoreClass);
        properties.put("org.quartz.jobStore.tablePrefix", tablePrefix);
        properties.put("org.quartz.jobStore.isClustered", isClustered);
        properties.put("org.quartz.jobStore.clusterCheckinInterval", clusterCheckinInterval);

        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(SchedulerFactoryBean.class);
        beanDefinitionBuilder.addPropertyValue("triggers", triggers);
        beanDefinitionBuilder.addPropertyValue("schedulerName", schedulerName);
        beanDefinitionBuilder.addPropertyReference("dataSource", dataSource);
        beanDefinitionBuilder.addPropertyValue("applicationContextSchedulerContextKey", applicationContextSchedulerContextKey);
        beanDefinitionBuilder.addPropertyValue("waitForJobsToCompleteOnShutdown", waitForJobsToCompleteOnShutdown);
        beanDefinitionBuilder.addPropertyValue("startupDelay", startupDelay);
        beanDefinitionBuilder.addPropertyValue("overwriteExistingJobs", overwriteExistingJobs);
        beanDefinitionBuilder.addPropertyValue("autoStartup", autoStartup);
        beanDefinitionBuilder.addPropertyValue("quartzProperties", properties);

        beanDefinitionBuilder.setDestroyMethodName("destroy");

        defaultListableBeanFactory.registerBeanDefinition("schedulerFactoryBean", beanDefinitionBuilder.getRawBeanDefinition());//注册到spring
    }


}
